package com.linkoog.devtools.code_generator.wizard.generate.database.template.panel;

import com.linkoog.devtools.code_generator.config.ui.TableSettingPanelBuilder;
import com.linkoog.devtools.code_generator.wizard.generate.database.template.tree.CheckBoxTreeCellRenderer;
import com.linkoog.devtools.code_generator.wizard.generate.database.template.tree.CheckBoxTreeNode;
import com.linkoog.devtools.code_generator.wizard.generate.database.template.tree.CheckBoxTreeNodeSelectionListener;
import com.linkoog.devtools.code_generator.template.model.ContainerNodeData;
import com.linkoog.devtools.code_generator.template.model.NodeData;
import com.linkoog.devtools.code_generator.template.model.node.FileNodeData;
import com.linkoog.devtools.code_generator.template.model.node.TemplateNodeData;
import com.linkoog.devtools.code_generator.setting.configurable.ui.template.ScrollableLabel;
import com.linkoog.devtools.code_generator.util.ProjectUtils;
import com.intellij.ide.util.PackageChooserDialog;
import com.intellij.openapi.module.Module;
import com.intellij.psi.PsiPackage;
import com.intellij.uiDesigner.core.GridConstraints;
import com.intellij.uiDesigner.core.GridLayoutManager;
import com.intellij.uiDesigner.core.Spacer;
import com.intellij.util.ui.JBUI;
import org.apache.commons.lang3.StringUtils;
import org.jetbrains.annotations.NotNull;

import javax.swing.*;
import javax.swing.border.LineBorder;
import javax.swing.border.TitledBorder;
import javax.swing.tree.DefaultTreeModel;
import javax.swing.tree.TreeNode;
import javax.swing.tree.TreeSelectionModel;
import java.awt.*;
import java.util.Enumeration;
import java.util.List;
import java.util.function.Consumer;

public class RightPanelBuilder {

    private JPanel myMainPanel;


    private JScrollPane describeScrollPanel;
    private JLabel describeLabel;

    private JScrollPane templateFileScrollPanel;
    private JTree templateFileTree;

    private JPanel templateSettingPanel;
    private JTextField authorTextField;

    private JTextField packageTextField;
    private JButton packageSelectButton;
    private JTextField fileEncodingTextField;

    private TemplateNodeData templateNodeData;

    private Consumer<PsiPackage> selectPackageCallback;
    private Module module;

    public RightPanelBuilder() {
        //myMainPanel.setBorder(new LineBorder(Color.LIGHT_GRAY));
        $$$setupUI$$$();
        myMainPanel.setMinimumSize(JBUI.size(400, -1));
        myMainPanel.setPreferredSize(JBUI.size(400, -1));


        describeScrollPanel.setBorder(new TitledBorder(new LineBorder(Color.LIGHT_GRAY), "模板说明"));
        templateFileScrollPanel.setBorder(new TitledBorder(new LineBorder(Color.LIGHT_GRAY), "模板内容"));
        templateSettingPanel.setBorder(new TitledBorder(new LineBorder(Color.LIGHT_GRAY), "模板设置"));


        TableSettingPanelBuilder tableSettingPanel = new TableSettingPanelBuilder();
        JPanel settingPanel = tableSettingPanel.getMyMainPanel();
        settingPanel.setBorder(BorderFactory.createEmptyBorder());
        settingPanel.setMinimumSize(JBUI.size(-1, 60));
        settingPanel.setPreferredSize(JBUI.size(-1, 60));

        templateSettingPanel.add(settingPanel, BorderLayout.NORTH);

        initTemplateFileTree();


        packageTextField.setEditable(false);
        //packageSelectButton.setVisible(false);
        packageSelectButton.addActionListener(e -> {
            chooserPackage(packageTextField.getText(),selectPackageCallback);
        });

        selectPackageCallback = (PsiPackage psiPackage) -> {
            packageTextField.setText(psiPackage.getQualifiedName());
        };


        fileEncodingTextField.setEditable(false);
        fileEncodingTextField.setText("utf-8");

    }

    /**
     * 选择包名
     *
     * @param defaultSelect 默认选中包名
     * @param consumer      完成事件
     */
    private void chooserPackage(String defaultSelect, Consumer<PsiPackage> consumer) {
        PackageChooserDialog chooser = null;
        if (module == null){
            chooser = new PackageChooserDialog("请选择package包", ProjectUtils.getCurrentProject());
        } else {
            chooser = new PackageChooserDialog("请选择package包", module);
        }

        chooser.selectPackage(defaultSelect);
        chooser.show();
        PsiPackage psiPackage = chooser.getSelectedPackage();
        if (psiPackage != null) {
            consumer.accept(psiPackage);
        }
        chooser.getDisposable().dispose();
    }


    private void initTemplateFileTree() {
        templateFileTree.putClientProperty("JTree.lineStyle", "Horizontal");
        templateFileTree.setRootVisible(false);
        templateFileTree.getSelectionModel().setSelectionMode(TreeSelectionModel.SINGLE_TREE_SELECTION);
        templateFileTree.addMouseListener(new CheckBoxTreeNodeSelectionListener());
        templateFileTree.setCellRenderer(new CheckBoxTreeCellRenderer());
        templateFileTree.setShowsRootHandles(true);

        CheckBoxTreeNode root = new CheckBoxTreeNode("");
        templateFileTree.setModel(new DefaultTreeModel(root));
    }


    public void resetData(TemplateNodeData templateNodeData) {
        if (templateNodeData != null) {
            this.templateNodeData = templateNodeData;
            this.describeLabel.setText(templateNodeData.getDescription());

            CheckBoxTreeNode root = new CheckBoxTreeNode(this.templateNodeData);
            List<NodeData> nodeDataList = templateNodeData.getChildNodeList();
            for (NodeData nodeData : nodeDataList) {
                addChildNode(root, nodeData);
            }

            templateFileTree.setModel(new DefaultTreeModel(root));
            //JTreeUtils.expandTree(templateFileTree);
        }
    }

    public TemplateNodeData getSelectedTemplateNodeData() {
        CheckBoxTreeNode root = (CheckBoxTreeNode) templateFileTree.getModel().getRoot();
        TemplateNodeData templateNodeData = this.templateNodeData.copy();

        handlerSelectedChildNode(root, templateNodeData);
        return templateNodeData;
    }


    private void handlerSelectedChildNode(CheckBoxTreeNode node, ContainerNodeData nodeData) {
        if (node == null || nodeData == null) {
            return;
        }

        Enumeration<TreeNode> children = node.children();
        while (children.hasMoreElements()) {
            CheckBoxTreeNode checkBoxTreeNode = (CheckBoxTreeNode) children.nextElement();
            if (checkBoxTreeNode.isSelected()) {
                NodeData data = ((NodeData) checkBoxTreeNode.getUserObject()).copy();
                nodeData.addChildNode(data);

                if (checkBoxTreeNode.getChildCount() > 0) {
                    ContainerNodeData containerNodeData = (ContainerNodeData) data;
                    handlerSelectedChildNode(checkBoxTreeNode, containerNodeData);
                }
            }
        }
    }


    private void addChildNode(CheckBoxTreeNode parentNode, NodeData nodeData) {
        CheckBoxTreeNode node = new CheckBoxTreeNode(nodeData);
        node.setSelected(true);
        parentNode.add(node);
        if (nodeData instanceof ContainerNodeData) {
            ContainerNodeData containerNodeData = (ContainerNodeData) nodeData;
            for (NodeData data : containerNodeData.getChildNodeList()) {
                addChildNode(node, data);
            }
        } else if (nodeData instanceof FileNodeData) {
            return;
        }
    }

    public void setPackageTextField(String text) {
        if (StringUtils.isNotBlank(text)) {
            packageTextField.setText(text);
        }
    }

    public void setSelectPackageCallback(Consumer<PsiPackage> selectPackageCallback) {
        if (selectPackageCallback != null){
            this.selectPackageCallback = selectPackageCallback;
        }
    }

    public void setModule(@NotNull Module module) {
        this.module = module;
    }

    public String getAuthorTextField() {
        return authorTextField.getText();
    }

    public void setAuthorTextField(String text) {
        if (StringUtils.isNotBlank(text)) {
            authorTextField.setText(text);
        }
    }


    public JPanel getMyMainPanel() {
        return myMainPanel;
    }

    private void createUIComponents() {
        describeLabel = new ScrollableLabel();
        describeLabel.setBorder(BorderFactory.createEmptyBorder());


    }

    /**
     * Method generated by IntelliJ IDEA GUI Designer
     * >>> IMPORTANT!! <<<
     * DO NOT edit this method OR call it in your code!
     *
     * @noinspection ALL
     */
    private void $$$setupUI$$$() {
        createUIComponents();
        myMainPanel = new JPanel();
        myMainPanel.setLayout(new GridLayoutManager(4, 2, new Insets(0, 0, 0, 0), -1, -1));
        final JPanel panel1 = new JPanel();
        panel1.setLayout(new BorderLayout(0, 0));
        myMainPanel.add(panel1, new GridConstraints(0, 0, 1, 2, GridConstraints.ANCHOR_CENTER, GridConstraints.FILL_BOTH, GridConstraints.SIZEPOLICY_CAN_SHRINK | GridConstraints.SIZEPOLICY_CAN_GROW, GridConstraints.SIZEPOLICY_CAN_SHRINK | GridConstraints.SIZEPOLICY_CAN_GROW, new Dimension(-1, 120), new Dimension(-1, 120), new Dimension(-1, 120), 0, false));
        describeScrollPanel = new JScrollPane();
        panel1.add(describeScrollPanel, BorderLayout.CENTER);
        describeLabel.setText("");
        describeScrollPanel.setViewportView(describeLabel);
        final Spacer spacer1 = new Spacer();
        myMainPanel.add(spacer1, new GridConstraints(2, 1, 2, 1, GridConstraints.ANCHOR_CENTER, GridConstraints.FILL_VERTICAL, 1, GridConstraints.SIZEPOLICY_WANT_GROW, null, null, null, 0, false));
        final JPanel panel2 = new JPanel();
        panel2.setLayout(new BorderLayout(0, 0));
        myMainPanel.add(panel2, new GridConstraints(1, 0, 1, 2, GridConstraints.ANCHOR_CENTER, GridConstraints.FILL_BOTH, GridConstraints.SIZEPOLICY_CAN_SHRINK | GridConstraints.SIZEPOLICY_CAN_GROW, GridConstraints.SIZEPOLICY_CAN_SHRINK | GridConstraints.SIZEPOLICY_CAN_GROW, new Dimension(-1, 230), new Dimension(-1, 230), new Dimension(-1, 230), 0, false));
        templateFileScrollPanel = new JScrollPane();
        panel2.add(templateFileScrollPanel, BorderLayout.CENTER);
        templateFileTree = new JTree();
        templateFileScrollPanel.setViewportView(templateFileTree);
        templateSettingPanel = new JPanel();
        templateSettingPanel.setLayout(new BorderLayout(0, 0));
        myMainPanel.add(templateSettingPanel, new GridConstraints(2, 0, 2, 1, GridConstraints.ANCHOR_CENTER, GridConstraints.FILL_BOTH, GridConstraints.SIZEPOLICY_CAN_SHRINK | GridConstraints.SIZEPOLICY_CAN_GROW, GridConstraints.SIZEPOLICY_CAN_SHRINK | GridConstraints.SIZEPOLICY_CAN_GROW, null, null, null, 0, false));
        final JPanel panel3 = new JPanel();
        panel3.setLayout(new GridLayoutManager(4, 4, new Insets(0, 7, 0, 7), 5, 5));
        templateSettingPanel.add(panel3, BorderLayout.CENTER);
        final Spacer spacer2 = new Spacer();
        panel3.add(spacer2, new GridConstraints(3, 0, 1, 2, GridConstraints.ANCHOR_CENTER, GridConstraints.FILL_VERTICAL, 1, GridConstraints.SIZEPOLICY_WANT_GROW, null, null, null, 0, false));
        final JLabel label1 = new JLabel();
        label1.setText("Save Package");
        panel3.add(label1, new GridConstraints(2, 0, 1, 1, GridConstraints.ANCHOR_WEST, GridConstraints.FILL_NONE, GridConstraints.SIZEPOLICY_FIXED, GridConstraints.SIZEPOLICY_FIXED, null, null, null, 0, false));
        packageTextField = new JTextField();
        panel3.add(packageTextField, new GridConstraints(2, 1, 1, 2, GridConstraints.ANCHOR_WEST, GridConstraints.FILL_HORIZONTAL, GridConstraints.SIZEPOLICY_WANT_GROW, GridConstraints.SIZEPOLICY_FIXED, null, new Dimension(150, -1), null, 0, false));
        packageSelectButton = new JButton();
        packageSelectButton.setText("选择...");
        panel3.add(packageSelectButton, new GridConstraints(2, 3, 1, 1, GridConstraints.ANCHOR_CENTER, GridConstraints.FILL_HORIZONTAL, GridConstraints.SIZEPOLICY_CAN_SHRINK | GridConstraints.SIZEPOLICY_CAN_GROW, GridConstraints.SIZEPOLICY_FIXED, null, null, null, 0, false));
        final JLabel label2 = new JLabel();
        label2.setText("File Encoding");
        panel3.add(label2, new GridConstraints(1, 0, 1, 1, GridConstraints.ANCHOR_WEST, GridConstraints.FILL_NONE, GridConstraints.SIZEPOLICY_FIXED, GridConstraints.SIZEPOLICY_FIXED, null, null, null, 0, false));
        fileEncodingTextField = new JTextField();
        panel3.add(fileEncodingTextField, new GridConstraints(1, 1, 1, 2, GridConstraints.ANCHOR_WEST, GridConstraints.FILL_HORIZONTAL, GridConstraints.SIZEPOLICY_WANT_GROW, GridConstraints.SIZEPOLICY_FIXED, null, new Dimension(150, -1), null, 0, false));
        final JLabel label3 = new JLabel();
        label3.setText("Author");
        panel3.add(label3, new GridConstraints(0, 0, 1, 1, GridConstraints.ANCHOR_WEST, GridConstraints.FILL_NONE, GridConstraints.SIZEPOLICY_FIXED, GridConstraints.SIZEPOLICY_FIXED, null, null, null, 0, false));
        authorTextField = new JTextField();
        panel3.add(authorTextField, new GridConstraints(0, 1, 1, 2, GridConstraints.ANCHOR_WEST, GridConstraints.FILL_HORIZONTAL, GridConstraints.SIZEPOLICY_WANT_GROW, GridConstraints.SIZEPOLICY_FIXED, null, new Dimension(150, -1), null, 0, false));
    }

    /**
     * @noinspection ALL
     */
    public JComponent $$$getRootComponent$$$() {
        return myMainPanel;
    }

}
